/**
 * Package:com.goldcitynet.util;
 * $Id: ConfigHelper.java,v 1.1.1.1 2009/03/23 09:21:18 zhangpei Exp $
 * Copyright(c) 2001-2005 www.afteryuan.com
 */
package com.afteryuan.util;

import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;

import java.net.URL;
import java.net.MalformedURLException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Properties;

/**
 * ConfigHelper
 * 配置文件读取工具
 * 应该至少能读取xml和properties类型文件
 * 文件部分内容摘抄自org.hibernate.util.ConfigHelpler
 * <p/>
 * <p><a href="ConfigHelper.java.html"><i>View Source</i></a></p>
 *
 * @author <a href="mailto:afteryuan@afteryuan.com">$Author: zhangpei $</a>
 * @version $Revision: 1.1.1.1 $
 */
public class ConfigHelper {
    private static Log log = LogFactory.getLog(ConfigHelper.class);

    /**
     * 定位文件路径，首先认为传入的是一个完整路径（如以file://开头）
     * 如果无法定位，则认为传入的是相对路径
     * 将在classpath下寻找可用资源并返回
     *
     * @param path 路径字符串
     * @return URL
     */
    public static final URL locateConfig(final String path) {
		try {
			return new URL(path);
		}
		catch(MalformedURLException e) {
			return findAsResource(path);
		}
	}

    /**
     *
     * @param path 传入的路径字符串
     * @return URL or null
     */
    public static final URL findAsResource(final String path) {
		URL url = null;

		// First, try to locate this resource through the current
		// context classloader.
		ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
		if (contextClassLoader!=null) {
			url = contextClassLoader.getResource(path);
		}
		if (url != null)
			return url;

		// Next, try to locate this resource through this class's classloader
		url = ConfigHelper.class.getClassLoader().getResource(path);
		if (url != null)
			return url;

		// Next, try to locate this resource through the system classloader
		url = ClassLoader.getSystemClassLoader().getResource(path);

		// Anywhere else we should look?
		return url;
	}

    /**
     * 获得配置文件的输入流,不能定位到文件或者不能打开文件都将抛出异常
     * @param path 文件路径
     * @return  InputStream 一个被请求的配置文件的输入流
     * @throws Exception 不能定位文件或不能打开文件的异常。应该将异常具体化？CouldNotLocateURLException+IOException？
     */
    public static final InputStream getConfigStream(final String path) throws Exception {
		final URL url = ConfigHelper.locateConfig(path);
		if (url == null) {
			String msg = "Unable to locate config file: " + path;
			log.error(msg);
            throw new Exception(msg);
        }
        return url.openStream();
	}

    /**
     * 获得配置文件的输入流,不能定位到文件或者不能打开文件都将抛出异常
     * 就是将输入流包装成Reader并返回
     * @param path 文件路径
     * @return  Reader 一个被请求的配置文件的输入流
     * @throws Exception 不能定位文件或不能打开文件的异常。
     */
    public static final Reader getConfigStreamReader(final String path) throws Exception {
		return new InputStreamReader( getConfigStream(path) );
	}

    /**
     * 获得配置文件的内容并包装为Properties返回
     * 该方法主要针对.properties类型文件
     * @param path 文件路径
     * @return 由请求的配置文件生成的Proerties对象
     * @throws Exception 非.properties类型文件或者文件找不到、打不开。
     */
    public static final Properties getConfigProperties(String path) throws Exception {
		try {
			Properties properties = new Properties();
			properties.load( getConfigStream(path) );
			return properties;
		}
		catch(IOException e) {
			throw new Exception("Unable to load properties from specified config file: " + path, e);
		}
	}

    /**
     * 获得配置文件的内容并包装为org.dom4j.Document返回
     * 该方法主要针对.xml类型文件
     * @param path 文件路径
     * @return 由请求的配置文件生成的Document对象，xml文件已经解析成功
     * @throws Exception 文件找不到，文件打不开，解析xml文件失败
     */
    public static final Document getConfigDocument(String path) throws Exception {
        SAXReader reader = new SAXReader();
        return reader.read(getConfigStream(path));
    }

    private ConfigHelper() {}
}
